home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / pyshared / PIL / PcxImagePlugin.py < prev    next >
Text File  |  2006-12-03  |  5KB  |  168 lines

  1. #
  2. # The Python Imaging Library.
  3. # $Id: PcxImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
  4. #
  5. # PCX file handling
  6. #
  7. # This format was originally used by ZSoft's popular PaintBrush
  8. # program for the IBM PC.  It is also supported by many MS-DOS and
  9. # Windows applications, including the Windows PaintBrush program in
  10. # Windows 3.
  11. #
  12. # history:
  13. # 1995-09-01 fl   Created
  14. # 1996-05-20 fl   Fixed RGB support
  15. # 1997-01-03 fl   Fixed 2-bit and 4-bit support
  16. # 1999-02-03 fl   Fixed 8-bit support (broken in 1.0b1)
  17. # 1999-02-07 fl   Added write support
  18. # 2002-06-09 fl   Made 2-bit and 4-bit support a bit more robust
  19. # 2002-07-30 fl   Seek from to current position, not beginning of file
  20. # 2003-06-03 fl   Extract DPI settings (info["dpi"])
  21. #
  22. # Copyright (c) 1997-2003 by Secret Labs AB.
  23. # Copyright (c) 1995-2003 by Fredrik Lundh.
  24. #
  25. # See the README file for information on usage and redistribution.
  26. #
  27.  
  28. __version__ = "0.6"
  29.  
  30. import Image, ImageFile, ImagePalette
  31.  
  32. def i16(c,o):
  33.     return ord(c[o]) + (ord(c[o+1])<<8)
  34.  
  35. def _accept(prefix):
  36.     return ord(prefix[0]) == 10 and ord(prefix[1]) in [0, 2, 3, 5]
  37.  
  38. ##
  39. # Image plugin for Paintbrush images.
  40.  
  41. class PcxImageFile(ImageFile.ImageFile):
  42.  
  43.     format = "PCX"
  44.     format_description = "Paintbrush"
  45.  
  46.     def _open(self):
  47.  
  48.         # header
  49.         s = self.fp.read(128)
  50.         if not _accept(s):
  51.             raise SyntaxError, "not a PCX file"
  52.  
  53.         # image
  54.         bbox = i16(s,4), i16(s,6), i16(s,8)+1, i16(s,10)+1
  55.         if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]:
  56.             raise SyntaxError, "bad PCX image size"
  57.  
  58.         # format
  59.         version = ord(s[1])
  60.         bits = ord(s[3])
  61.         planes = ord(s[65])
  62.         stride = i16(s,66)
  63.  
  64.         self.info["dpi"] = i16(s,12), i16(s,14)
  65.  
  66.         if bits == 1 and planes == 1:
  67.             mode = rawmode = "1"
  68.  
  69.         elif bits == 1 and planes in (2, 4):
  70.             mode = "P"
  71.             rawmode = "P;%dL" % planes
  72.             self.palette = ImagePalette.raw("RGB", s[16:64])
  73.  
  74.         elif version == 5 and bits == 8 and planes == 1:
  75.             mode = rawmode = "L"
  76.             # FIXME: hey, this doesn't work with the incremental loader !!!
  77.             self.fp.seek(-769, 2)
  78.             s = self.fp.read(769)
  79.             if len(s) == 769 and ord(s[0]) == 12:
  80.                 # check if the palette is linear greyscale
  81.                 for i in range(256):
  82.                     if s[i*3+1:i*3+4] != chr(i)*3:
  83.                         mode = rawmode = "P"
  84.                         break
  85.                 if mode == "P":
  86.                     self.palette = ImagePalette.raw("RGB", s[1:])
  87.             self.fp.seek(128)
  88.  
  89.         elif version == 5 and bits == 8 and planes == 3:
  90.             mode = "RGB"
  91.             rawmode = "RGB;L"
  92.  
  93.         else:
  94.             raise IOError, "unknown PCX mode"
  95.  
  96.         self.mode = mode
  97.         self.size = bbox[2]-bbox[0], bbox[3]-bbox[1]
  98.  
  99.         bbox = (0, 0) + self.size
  100.  
  101.         self.tile = [("pcx", bbox, self.fp.tell(), (rawmode, planes * stride))]
  102.  
  103. # --------------------------------------------------------------------
  104. # save PCX files
  105.  
  106. SAVE = {
  107.     # mode: (version, bits, planes, raw mode)
  108.     "1": (2, 1, 1, "1"),
  109.     "L": (5, 8, 1, "L"),
  110.     "P": (5, 8, 1, "P"),
  111.     "RGB": (5, 8, 3, "RGB;L"),
  112. }
  113.  
  114. def o16(i):
  115.     return chr(i&255) + chr(i>>8&255)
  116.  
  117. def _save(im, fp, filename, check=0):
  118.  
  119.     try:
  120.         version, bits, planes, rawmode = SAVE[im.mode]
  121.     except KeyError:
  122.         raise ValueError, "Cannot save %s images as PCX" % im.mode
  123.  
  124.     if check:
  125.         return check
  126.  
  127.     # bytes per plane
  128.     stride = (im.size[0] * bits + 7) / 8
  129.  
  130.     # under windows, we could determine the current screen size with
  131.     # "Image.core.display_mode()[1]", but I think that's overkill...
  132.  
  133.     screen = im.size
  134.  
  135.     dpi = 100, 100
  136.  
  137.     # PCX header
  138.     fp.write(
  139.         chr(10) + chr(version) + chr(1) + chr(bits) + o16(0) +
  140.         o16(0) + o16(im.size[0]-1) + o16(im.size[1]-1) + o16(dpi[0]) +
  141.         o16(dpi[1]) + chr(0)*24 + chr(255)*24 + chr(0) + chr(planes) +
  142.         o16(stride) + o16(1) + o16(screen[0]) + o16(screen[1]) +
  143.         chr(0)*54
  144.         )
  145.  
  146.     assert fp.tell() == 128
  147.  
  148.     ImageFile._save(im, fp, [("pcx", (0,0)+im.size, 0,
  149.                               (rawmode, bits*planes))])
  150.  
  151.     if im.mode == "P":
  152.         # colour palette
  153.         fp.write(chr(12))
  154.         fp.write(im.im.getpalette("RGB", "RGB")) # 768 bytes
  155.     elif im.mode == "L":
  156.         # greyscale palette
  157.         fp.write(chr(12))
  158.         for i in range(256):
  159.             fp.write(chr(i)*3)
  160.  
  161. # --------------------------------------------------------------------
  162. # registry
  163.  
  164. Image.register_open("PCX", PcxImageFile, _accept)
  165. Image.register_save("PCX", _save)
  166.  
  167. Image.register_extension("PCX", ".pcx")
  168.